//////////////////////////////////////////////////////////////////////////////////
//	 Copyright 2011 by Yosef Grabivker, ryuho@homenetworksoft.com
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
//////////////////////////////////////////////////////////////////////////////////

#include "pingengine.h"

#define PING_TIMES 3

CPingEngine::CPingEngine():wxThread(wxTHREAD_JOINABLE), m_ptrObserver(NULL)
{

}

CPingEngine::~CPingEngine()
{
	Stop();
}

void CPingEngine::Start()
{
	if ( wxTHREAD_NO_ERROR==Create() )
	{
		SetPriority(WXTHREAD_MIN_PRIORITY);

		if ( wxTHREAD_NO_ERROR !=Run() )
		{

		}
	}
}

void CPingEngine::Stop()
{
	Reset();

	m_bWorking = false;

	if ( IsAlive() )
	{
		wxThread::Wait();
	}
}


void CPingEngine::Reset()
{
	m_idx = 0;
}


void  CPingEngine::SetPingList(const PINGDATALIST& lst)
{
	wxCriticalSectionLocker locker(m_csPing);	
	Reset();
	m_lstPing = lst;

}

bool CPingEngine::GetJob(PingData& entryOut, int& idx)
{
	bool bRes(false);

	wxCriticalSectionLocker locker(m_csPing);

	time_t tNow = time(NULL);

	if ( !m_lstPing.empty() )
	{
		try
		{
			if ( m_idx>= m_lstPing.size() )
			{
				m_idx = 0;
			}

			do
			{
				PingData& entry = m_lstPing[m_idx++];

				if ( entry.cStatus == cPingActive &&
					 tNow-entry.tLastPinged>entry.stInterval )
				{
					idx = m_idx-1;
					entry.tLastPinged = tNow;

					entryOut = entry;

					bRes = true;
					break;
				}
			}while(m_idx<m_lstPing.size());

		}catch(...)
		{
		}
	}

	return bRes;
}

//////////////////////////////////////////////////////////////////////////
//Ping Loop
void* CPingEngine::Entry()
{
	void* pRet(NULL);

	m_bWorking = m_bThreadRun = true;

	while ( m_bWorking )
	{
		PingData entry;
		int idx;

		if ( GetJob(entry, idx) )
		{
			PingEng(entry, idx);
		}
		else
		{
			wxThread::Sleep(20);
		}
	}

	m_bThreadRun = false;

	return pRet;
}

void CPingEngine::PingEng(const PingData& entry, int idx)
{
	try
	{
		PINGRESULT result;
		m_pinger( entry.strHost, PING_TIMES,  result);

		if ( m_ptrObserver )
		{
			m_ptrObserver->OnPingResult(idx, result);
		}
		
	}catch(...)
	{

	}
}
